
import shaderlight from '../shader/lambert.light.frag.wgsl?raw'

function createLightingPipeline(device: GPUDevice, format: GPUTextureFormat, pointLightCount: number, enableShadow: boolean = true ) {
    const lightingVertexShader = `
        @vertex
        fn main(@location(0) position: vec2<f32>) -> @builtin(position) vec4<f32> {
            return vec4<f32>(position, 0.0, 1.0);
        }
    `;

    if(pointLightCount < 1){
        pointLightCount = 1;
    }

    let lightingFragmentShader = 
    `
    const pointLightCount: i32 = ${pointLightCount};
    ` + shaderlight;

    
    lightingFragmentShader = 
    `
    const shadowMapEnabled: bool = ${enableShadow}; 
    ` + lightingFragmentShader;

    
    const shadowOptionsBuffer = device.createBuffer({
        size: 4, // 布尔值通常用 4 字节对齐
        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
    });
    // 更新缓冲区
    const shadowEnabled = new Uint32Array([0]); // 1 表示 true，0 表示 false
    device.queue.writeBuffer(shadowOptionsBuffer, 0, shadowEnabled);

    // 创建绑定组布局
    const bindGroupLayout = device.createBindGroupLayout({
        entries: [
            {
                binding: 0,
                visibility: GPUShaderStage.FRAGMENT,
                texture: {
                    sampleType: 'float',
                },
            },
            {
                binding: 1,
                visibility: GPUShaderStage.FRAGMENT,
                texture: {
                    sampleType: 'float',
                },
            },
            {
                binding: 2,
                visibility: GPUShaderStage.FRAGMENT,
                texture: {
                    sampleType: 'float',
                },
            },
            {
                binding: 3,
                visibility: GPUShaderStage.FRAGMENT,
                buffer: {
                    type: 'uniform', // 缓冲区类型
                },
            },
            {
                binding: 4,
                visibility: GPUShaderStage.FRAGMENT,
                texture: {
                    sampleType: "depth", // 关键：声明为深度纹理
                    viewDimension: "2d", // 视图维度（2D/Cube等）
                },
            },
            {
                binding: 5,
                visibility: GPUShaderStage.FRAGMENT,
                sampler: {
                    type: "comparison", // 关键：标记为比较采样器
                },
            },
            {
                binding: 6,
                visibility: GPUShaderStage.FRAGMENT,
                buffer: {
                    type: 'uniform', // 缓冲区类型
                },
            },
        ],
    });

    const bindGroupLayoutLights = device.createBindGroupLayout({
        entries: [
            {
                binding: 0,
                visibility: GPUShaderStage.FRAGMENT,
                buffer: {
                    type: 'uniform', // 缓冲区类型
                },
            },
            {
                binding: 1,
                visibility: GPUShaderStage.FRAGMENT,
                buffer: {
                    type: 'uniform', // 缓冲区类型
                },
            },
            {
                binding: 2,
                visibility: GPUShaderStage.FRAGMENT,
                buffer: {
                    type: 'uniform', // 缓冲区类型
                },
            },
            {
                binding: 3,
                visibility: GPUShaderStage.FRAGMENT,
                buffer: {
                    type: 'uniform', // 缓冲区类型
                },
            },
            {
                binding: 4,
                visibility: GPUShaderStage.FRAGMENT,
                buffer: {
                    type: 'uniform', // 缓冲区类型
                },
            },
            {
                binding: 5,
                visibility: GPUShaderStage.FRAGMENT,
                buffer: {
                    type: 'uniform', // 缓冲区类型
                },
            },
        ],
    });

    // 创建渲染管线布局
    const pipelineLayout = device.createPipelineLayout({
        bindGroupLayouts: [bindGroupLayout, bindGroupLayoutLights],
    });

    const pipeline = device.createRenderPipeline({
        layout: pipelineLayout, // 显式指定布局
        vertex: {
            module: device.createShaderModule({
                code: lightingVertexShader,
            }),
            entryPoint: 'main',
            buffers: [
                {
                    arrayStride: 2 * 4, // 每个顶点 2 个浮点数（x, y），每个浮点数 4 字节
                    attributes: [
                        {
                            shaderLocation: 0, // 对应 @location(0)
                            offset: 0,
                            format: 'float32x2', // 2 个浮点数
                        },
                    ],
                },
            ],
        },
        fragment: {
            module: device.createShaderModule({
                code: lightingFragmentShader,
            }),
            entryPoint: 'main',
            targets: [
                { format: format },
            ],
        },
        primitive: {
            topology: 'triangle-list',
        },
    });

    // create a uniform buffer to store pointLight
    const ambientBuffer = device.createBuffer({
        label: 'GPUBuffer store 4x4 matrix',
        size: 1 * 4, // 1 x float32: intensity f32
        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
    })
    // create a uniform buffer to store pointLight
    const pointOptionBuffer = device.createBuffer({
        label: 'GPUBuffer store 4x4 matrix',
        size: 4 * 4, //  4 configs
        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
    })
    // create a uniform buffer to store pointLight
    const pointPositionBuffer = device.createBuffer({
        label: 'GPUBuffer store 4x4 matrix',
        size: 4 * 4 * pointLightCount, //  position vec4 x pointLightCount
        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
    })
    // create a uniform buffer to store dirLight
    const directionalBuffer = device.createBuffer({
        label: 'GPUBuffer store 4x4 matrix',
        size: 8 * 4, // 8 x float32: position vec4 + 4 configs
        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
    })

    
    const modelViewAllBuffer = device.createBuffer({
        label: 'GPUBuffer store 4x4 matrix',
        size: 4 * 4 * 4, // 4 x 4 x float32
        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
    })

    // create a uniform buffer to store pointLight
    const pointColorBuffer = device.createBuffer({
        label: 'GPUBuffer store 4x4 matrix',
        size: 4 * 4 * pointLightCount, //  position vec4 x pointLightCount
        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
    })

    // create a uniform group for light Matrix
    const lightGroup = device.createBindGroup({
        label: 'Uniform Group 4 light pipeline',
        layout: pipeline.getBindGroupLayout(1),
        entries: [
            {
                binding: 0,
                resource: {
                    buffer: ambientBuffer
                }
            },
            {
                binding: 1,
                resource: {
                    buffer: pointOptionBuffer
                }
            },
            {
                binding: 2,
                resource: {
                    buffer: pointPositionBuffer
                }
            },
            {
                binding: 3,
                resource: {
                    buffer: directionalBuffer
                }
            },
            {
                binding: 4,
                resource: {
                    buffer: modelViewAllBuffer
                }
            },
            {
                binding: 5,
                resource: {
                    buffer: pointColorBuffer
                }
            }
        ]
    })

    return { pipeline, ambientBuffer, modelViewAllBuffer, 
        pointOptionBuffer, pointPositionBuffer, pointColorBuffer,
        directionalBuffer, lightGroup, shadowOptionsBuffer };
}

export { createLightingPipeline };